using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
using UnityEngine.Rendering;

namespace Nirvana
{
    public class SerializedMesh : SerializedGameObject
    {
        /// <summary>
        /// mesh的材质地址所存储的数组的索引
        /// </summary>
        public int MatPathId;

        /// <summary>
        /// mesh的MeshFilter地址所存储的数组的索引
        /// </summary>
        public int MeshPathId;

        /// <summary>
        /// mesh半径
        /// </summary>
        public float Radius;

        /// <summary>
        /// mesh中心
        /// </summary>
        public Vector3 Center;

        /// <summary>
        /// 表面积
        /// </summary>
        public Vector4 SurfaceArea;

        // ======Mesh保存数据======
        public int LightmapIndex;

        public Vector4 LightmapScaleOffset;

        public LightProbeUsage LightProbeUsage;

        public ReflectionProbeUsage ReflectionProbeUsage;

        public bool ReceiveShadows;

        public ShadowCastingMode ShadowCastingMode;

        public uint RenderingLayerMask;

        public bool AllowOcclusionWhenDynamic;
        // ======Mesh保存数据======

        /// <summary>
        /// 资源加载状态
        /// </summary>
        protected ResLoadState _loadState = ResLoadState.UnLoad;

        /// <summary>
        /// 运行时的MeshFilter
        /// </summary>
        private MeshFilter _meshFilter;

        /// <summary>
        /// 运行时的MeshFilter
        /// </summary>
        private MeshRenderer _meshRenderer;

        /// <summary>
        /// 运行时异步加载资源计数
        /// </summary>
        private int _loadCount;

        public override void Init(Transform parent, Transform node, BigWorld.GetResPath func)
        {
            base.Init(parent, node, func);
            if (node != null)
            {
                node.gameObject.SetActive(false);
            }
        }

        protected override void OnWrite(BinaryWriter writer)
        {
            writer.Write(MatPathId);
            writer.Write(MeshPathId);
            writer.Write(Radius);
            writer.Write(Center);
            writer.Write(SurfaceArea);
        }

        protected override void OnRead(BinaryReader reader)
        {
            MatPathId = reader.ReadInt32();
            MeshPathId = reader.ReadInt32();
            Radius = reader.ReadSingle();
            Center = reader.ReadVector3();
            SurfaceArea = reader.ReadVector4();
        }

        public override void Load()
        {
            if (MatPathId < 0 || MeshPathId < 0) return;
            if (_loadState == ResLoadState.Loading || _loadState == ResLoadState.Loaded) return;
            _loadState = ResLoadState.Loading;
            if (_meshRenderer == null)
            {
                _meshRenderer = Node.GetOrAddComponent<MeshRenderer>();
                _meshRenderer.enabled = false;
            }

            if (_meshFilter == null)
            {
                _meshFilter = Node.GetOrAddComponent<MeshFilter>();
            }

            LoadHelper.Load(GetResPathFunc(MatPathId), OnMatLoadComplete);
            LoadHelper.Load(GetResPathFunc(MeshPathId), OnMeshLoadComplete);
        }

        public override void UnLoad()
        {
            if (MatPathId < 0 || MeshPathId < 0) return;
            if (_loadState == ResLoadState.UnLoad) return;
            _loadState = ResLoadState.UnLoad;
            if (_meshRenderer != null)
            {
                _meshRenderer.enabled = false;
                if (_meshRenderer.sharedMaterial != null)
                {
                    _meshRenderer.sharedMaterial = null;
                }
            }

            if (_meshFilter != null && _meshFilter.sharedMesh != null)
            {
                _meshFilter.sharedMesh = null;
            }

            if (Node != null)
            {
                Node.gameObject.SetActive(false);
            }

            LoadHelper.UnLoad(GetResPathFunc(MatPathId));
            LoadHelper.UnLoad(GetResPathFunc(MeshPathId));
            _loadCount = 0;
        }

        public override void Update()
        {
            // 正在加载不考虑更新位置
            if (_loadState == ResLoadState.Loading) return;
            ActionState state = BigWorldHelper.CalcProjectSize(ref SurfaceArea, ref Center, ref Radius);
            switch (state)
            {
                case ActionState.Nothing:
                    return;
                case ActionState.Load:
                    Load();
                    break;
                case ActionState.UnLoad:
                    UnLoad();
                    break;
            }
        }

        protected override void OnClear()
        {
            _loadCount = 0;
            _meshFilter = null;
            _meshRenderer = null;
        }

        private void OnMatLoadComplete(object res)
        {
            if (_meshRenderer != null)
            {
                _meshRenderer.sharedMaterial = res as Material;
                SetData(_meshRenderer);
            }

            _loadCount++;
            CheckAssets();
        }

        private void OnMeshLoadComplete(object res)
        {
            if (_meshFilter != null)
            {
                _meshFilter.sharedMesh = res as Mesh;
            }

            _loadCount++;
            CheckAssets();
        }

        private void CheckAssets()
        {
            if (_loadCount != 2) return;
            _loadState = ResLoadState.Loaded;
            if (Node != null)
            {
                Node.gameObject.SetActive(true);
            }

            if (_meshRenderer != null)
            {
                _meshRenderer.enabled = true;
            }
        }

        /// <summary>
        /// 收集mesh所需要的数据来导出二进制
        /// </summary>
        /// <param name="renderer"></param>
        public void CollectData(MeshRenderer renderer)
        {
            LightmapIndex = renderer.lightmapIndex;
            LightmapScaleOffset = renderer.lightmapScaleOffset;
            LightProbeUsage = renderer.lightProbeUsage;
            ReflectionProbeUsage = renderer.reflectionProbeUsage;
            ReceiveShadows = renderer.receiveShadows;
            ShadowCastingMode = renderer.shadowCastingMode;
            RenderingLayerMask = renderer.renderingLayerMask;
            AllowOcclusionWhenDynamic = renderer.allowOcclusionWhenDynamic;
        }

        /// <summary>
        /// 运行时还原数据
        /// </summary>
        /// <param name="renderer"></param>
        public void SetData(MeshRenderer renderer)
        {
            renderer.lightmapIndex = LightmapIndex;
            renderer.lightmapScaleOffset = LightmapScaleOffset;
            renderer.lightProbeUsage = LightProbeUsage;
            renderer.reflectionProbeUsage = ReflectionProbeUsage;
            renderer.shadowCastingMode = ShadowCastingMode;
            renderer.renderingLayerMask = RenderingLayerMask;
            renderer.allowOcclusionWhenDynamic = AllowOcclusionWhenDynamic;
        }
    }
}